/*******************************************************************
*
*    DESCRIPTION:
*
*    AUTHOR:LiuHui
*
*    HISTORY:
*
*    DATE:9/6/2006
*
*******************************************************************/
#include "head.h"
#include "config.h"
#include "xmlutil.h"
//global
GtkListStore *app_list_store;//list store for app
GtkListStore *service_list_store;//list store for service
GtkTreeViewColumn *column;
GtkCellRenderer *cell_renderer;
GtkTreeSelection *app_selection;
GtkTreeSelection *service_selection;
/*
 *Function Name:AddListeningServiceToListStore
 *
 *Parameters:
 *
 *Description:
 *
 *Returns:
 *
 */
void AddListeningServiceToListStore(GtkListStore *service_list_store)
{
#ifdef _DEBUG
	printf("Enter on_refreshedbutton_clicked\n");
#endif
	FILE *fp;
	char tcpitem[256];
	memset(tcpitem, 0, 256);
	fp = fopen("/proc/net/tcp", "r");
	assert(fp != NULL);
	int k = 0;
	int i;
	char app_path[128];
	int sport;
	char csport[8];
	memset(csport, 0, 8);
	while ( fgets(tcpitem, 256, fp) != NULL )
	{
		if ( k == 0 )
		{
			k++;
			continue;//skip first line
		}
		else
		{
			char *mark = strnchr(tcpitem, ':', 3);
			assert(mark != NULL);
			char status[5];
			char cinode[10];
			char citem_inode[10];
			memset(status, 0, 5);
			strncpy(status, mark + 6, 2);//point to /proc/net/tcp "st" filed
			if ( strcmp(status, "0A") == 0 )//find listing item
			{
				char hex_sport[6];
				memset(hex_sport, 0, 6);
				char *mark2 = strchr(tcpitem + 15, ' ');
				int sport_sz = mark2 - (tcpitem + 15);
				strncpy(hex_sport, tcpitem + 15, sport_sz);
				sport = strtol(hex_sport, NULL, 16);
				for ( i = 0; i < service_counter; i ++ )
				{
					if ( sport == service_conf[i].sport )
					{
						break;
					}
				}

				if ( i == service_counter )//service not in xml config file
				{

					memset(app_path, 0, 256);
					GetAppInfo(6, sport, app_path);
					char *mark = strrchr(app_path, '/');
					assert(mark != NULL);
					sprintf(csport, "%d", sport);

					//add to liststore to show 
					GtkTreeIter iter;
					gtk_list_store_append(service_list_store, &iter);
					gtk_list_store_set(service_list_store, &iter, 0, mark + 1, 2, csport, 3, FALSE, -1);
				}
				else
				{
					if ( service_conf[i].allow == 1 )
					{

						memset(app_path, 0, 256);
						GetAppInfo(6, sport, app_path);
						char *mark = strrchr(app_path, '/');
						assert(mark != NULL);
						sprintf(csport, "%d", sport);

						//add to liststore to show 
						GtkTreeIter iter;
						gtk_list_store_append(service_list_store, &iter);
						gtk_list_store_set(service_list_store, &iter, 0, mark + 1, 2, csport, 3, TRUE, -1);
					}
				}
			}
		}
	}
}

/*
 *Function Name:on_refreshbutton_clicked
 *
 *Parameters:
 *
 *Description:
 *
 *Returns:
 *
 */
void on_refreshbutton_clicked(GtkButton *button,
							  gpointer   user_data) 
{
	XmlInitServiceListStore(service_list_store);
	AddListeningServiceToListStore(service_list_store);
}
/*
 *Function Name:show_or_hide_refresh_button
 *
 *Parameters:
 *
 *Description:
 *
 *Returns:
 *
 */
void show_or_hide_refresh_button(GtkNotebook     *notebook,
								 GtkNotebookPage *page,
								 guint            page_num,
								 gpointer         user_data) 
{
	GtkWidget *fresh_button = glade_xml_get_widget(gui_xml, "button_refresh");
	if ( page_num == 1 )
	{
		gtk_widget_show(fresh_button);
	}
	else
	{
		gtk_widget_hide(fresh_button);
	}
}
/*
 *Function Name:AppCellrenderToggled
 *
 *Parameters:
 *
 *Description:when checkbutton is toggled:
 *1,active or unactive the checkbutton
 *2,modify the xmlfile 3,clean or add rules
 *
 *Returns:
 *
 */
void AppCellrenderToggled(GtkCellRendererToggle *cell_renderer,
						  gchar                 *path,
						  gpointer               user_data)
{
#ifdef _DEBUG
	printf("the path is:%s\n", (char*)path);
#endif
	GtkTreeIter iter;
	gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(app_list_store), &iter, path);

	//get checkbutton's status
	gboolean status;
	char *app_name;
	gtk_tree_model_get(GTK_TREE_MODEL(app_list_store), &iter, 0, &app_name, 2, &status, -1);
#ifdef _DEBUG
	printf("Get value from cellrenderer:appname:%s, status:%d\n", app_name, status);
#endif
	int k;
	//change the status
	if ( status == 0 )//do change:allow = yes, slect checkbutton and add entry in app_conf
	{
		GValue i;
		i.g_type = G_TYPE_BOOLEAN;
		i.data[0].v_int = 1;
		gtk_list_store_set_value(app_list_store, &iter, 2, &i);
		XmlAllowApp(app_name);
		//find the entry in app_conf and mark it allow
		for ( k = 0; k < app_counter; k++ )
		{
			if ( strcmp(app_conf[k].name, app_name) == 0 )
			{
#ifdef _DEBUG
				printf("In AppCellrenderToggled:find appname in app_conf\n");
#endif
				app_conf[k].allow = 1;
			}
		}

	}
	else
	{
		GValue i;
		i.g_type = G_TYPE_BOOLEAN;
		i.data[0].v_int = 0;
		gtk_list_store_set_value(app_list_store, &iter, 2, &i);
		XmlDenyApp(app_name);
		//find the entry in app_conf and mark it deny
		for ( k = 0; k < app_counter; k++ )
		{
			if ( strcmp(app_conf[k].name, app_name) == 0 )
			{

#ifdef _DEBUG
				printf("In AppCellrenderToggled:find appname in app_conf\n");
#endif
				app_conf[k].allow = 0;
			}
		}

	}
}

/*
 *Function Name:ServiceCellrenderToggled
 *
 *Parameters:
 *
 *Description:when checkbutton is toggled:
 *1,active or unactive the checkbutton
 *2,modify the xmlfile 3,clean or add rules
 *4,modify the service_conf app
 *Returns:
 *
 */
void ServiceCellrenderToggled(GtkCellRendererToggle *cell_renderer,
							  gchar                 *path,
							  gpointer               user_data)
{
#ifdef _DEBUG
	printf("the path is:%s\n", (char*)path);
#endif
	GtkTreeIter iter;
	gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(service_list_store), &iter, path);

	//get checkbutton's status
	gboolean status;
	char *service_name;
	char *sport;
	gtk_tree_model_get(GTK_TREE_MODEL(service_list_store), &iter, 0, &service_name, 2, &sport, 3, &status, -1);
#ifdef _DEBUG
	printf("Get value from cellrenderer:appname:%s, status:%d\n", service_name, status);
#endif
	int k;
	int listen_port = atoi(sport);
	//change the status
	if ( status == 0 )
	{
		GValue i;
		i.g_type = G_TYPE_BOOLEAN;
		i.data[0].v_int = 1;
		gtk_list_store_set_value(service_list_store, &iter, 3, &i);//make check button selected
		//find the entry in app_conf and mark it allow
		for ( k = 0; k < service_counter; k++ )
		{
			if ( service_conf[k].sport == listen_port )
			{
#ifdef _DEBUG
				printf("In AppCellrenderToggled:find appname in app_conf\n");
#endif
				XmlAllowService(service_name);
				service_conf[k].allow = 1;
			}
		}
		if ( k == service_counter )//not in service_conf
		{
			//add to service_conf array
			service_conf[k].name = service_name;
			service_conf[k].allow = 1;
			service_conf[k].seqnum = k;
			service_conf[k].sport = listen_port;
			service_counter ++;
			AddServiceName(conf_xml, 1, service_name, listen_port, service_counter);
		}
		else
		{
			free(service_name);
		}
		//add rules
		IptablesOpenService(listen_port);
		free(sport);

	}
	else
	{
		GValue i;
		i.g_type = G_TYPE_BOOLEAN;
		i.data[0].v_int = 0;
		gtk_list_store_set_value(service_list_store, &iter, 3, &i);
		XmlDenyService(service_name);
		//find the entry in service_conf and mark it deny
		for ( k = 0; k < service_counter; k++ )
		{
			if ( service_conf[k].sport == listen_port )
			{

#ifdef _DEBUG
				printf("In AppCellrenderToggled:find appname in app_conf\n");
#endif
				service_conf[k].allow = 0;
				//delete the rules
				IptablesCancelService(listen_port);
			}
		}

		free(service_name);
		free(sport);
	}
}
/*
 *Function Name:MainWindowInit
 *
 *Parameters:
 *
 *Description:
 *
 *Returns:
 *
 */
void MainWindowInit()
{


	//create app list mode
	app_list_store = gtk_list_store_new(3, G_TYPE_STRING,//appname
										G_TYPE_STRING,//apppath
										G_TYPE_BOOLEAN//check_button
									   );
	//create service list mode
	service_list_store = gtk_list_store_new(4, G_TYPE_STRING,//service name
											G_TYPE_STRING,//service path
											G_TYPE_STRING,//listening port
											G_TYPE_BOOLEAN//check button
										   );
	GtkWidget *app_treeview = glade_xml_get_widget(gui_xml, "treeview_app");
	GtkWidget *service_treeview = glade_xml_get_widget(gui_xml, "treeview_service");

	gtk_tree_view_set_model(GTK_TREE_VIEW(app_treeview), app_list_store);
	gtk_tree_view_set_model(GTK_TREE_VIEW(service_treeview), service_list_store);

	//get the selection object
	app_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(app_treeview));
	service_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(service_treeview));
	gtk_tree_selection_set_mode(app_selection, GTK_SELECTION_SINGLE);
	gtk_tree_selection_set_mode(service_selection, GTK_SELECTION_SINGLE);

	//init app column and cellrender
	//add  tree columns and map three cell
	//add first column named "name" and map the cellrender
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "name");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(app_treeview), column);
	//map appname cell on appname column
	cell_renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "text", 0, NULL);//text is the attr of cell

	//add second column named "path" and map the cellrender
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "path");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(app_treeview), column);
	//map path cell on gropu column
	cell_renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "text", 1, NULL);

	//add third column named "network access" and map checkbutton on it
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "network access");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(app_treeview), column);
	//map checkbutton cell on username column
	cell_renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "active", 2, NULL);
	gtk_signal_connect(cell_renderer, "toggled", AppCellrenderToggled, NULL);

	//init service column and cellrender
	//add  four columns and map four cell
	//add first column named "name" and map the cellrender
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "name");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(service_treeview), column);
	//map servicename cell on servicename column
	cell_renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "text", 0, NULL);//text is the attr of cell

	//add second column named "path" and map the cellrender
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "path");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(service_treeview), column);
	//map path cell on gropu column
	cell_renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "text", 1, NULL);

	//add third column named "listening port" and map the cellrender
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "listening port");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(service_treeview), column);
	//map path cell on gropu column
	cell_renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "text", 2, NULL);

	//add fourth column named "network access" and map checkbutton on it
	column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_title(column, "network access");
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
	gtk_tree_view_append_column(GTK_TREE_VIEW(service_treeview), column);
	//map checkbutton cell on username column
	cell_renderer = gtk_cell_renderer_toggle_new();
	gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
	gtk_tree_view_column_set_attributes(column, cell_renderer, "active", 3, NULL);
	gtk_signal_connect(cell_renderer, "toggled", ServiceCellrenderToggled, NULL);
	//init the value of treeview from xml
	XmlInitAppListStore(app_list_store);
	XmlInitServiceListStore(service_list_store);
	AddListeningServiceToListStore(service_list_store);
}
